package com.bestcem.xm.award.grpc.service;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.bestcem.xm.award.entity.pojo.AwardRequestDO;
import com.bestcem.xm.award.enums.DeviceTypeEnum;
import com.bestcem.xm.award.grpc.service.param.requestaward.GetRequestAwardParam;
import com.bestcem.xm.award.grpc.v1.services.*;
import com.bestcem.xm.award.service.impl.AwardDispatcher;
import com.bestcem.xm.common.core.domain.web.RpcStatusResult;
import com.bestcem.xm.common.core.domain.web.ServiceResult;
import com.bestcem.xm.common.core.sign.grpc.core.GrpcTemplate;
import com.bestcem.xm.common.core.uitls.GRpcUtil;
import io.grpc.stub.StreamObserver;
import lombok.extern.slf4j.Slf4j;
import net.devh.boot.grpc.server.service.GrpcService;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import javax.validation.ConstraintViolation;
import java.util.Set;

/**
 * 答题端完成答卷获取奖励
 *
 * @author jie.yao <jie.yao@idiaoyan.com>
 * @version v1.0
 * @date 2021/6/29 17:57
 */
@GrpcService
@Slf4j
public class RequestAwardGrpcService extends RequestAwardServiceGrpc.RequestAwardServiceImplBase {

    @Resource
    private AwardDispatcher awardDispatcher;

    @Resource
    private GrpcTemplate grpcTemplate;

    /**
     * 答题端完成答卷获取奖励
     *
     * @param request          请求参数
     * @param responseObserver 输出流
     */
    @Override
    public void getRequestAward(GetRequestAwardRequest request, StreamObserver<GetRequestAwardResponse> responseObserver) {
        GetRequestAwardResponse.Builder builder = GetRequestAwardResponse.newBuilder();

        // 验签
        ServiceResult<?> checkSignResult = grpcTemplate.checkSign(request);
        if (!checkSignResult.isSuccess()) {
            builder.setStatus(RpcStatusResult.error(checkSignResult.getMsg()));
            responseObserver.onNext(builder.build());
            responseObserver.onCompleted();
            return;
        }
        // 检查投放信息
        if (StrUtil.isEmpty(request.getDeliver())) {
            builder.setStatus(RpcStatusResult.error("投放信息为空！"));
            responseObserver.onNext(builder.build());
            responseObserver.onCompleted();
            return;
        }
        // 检查答卷信息
        if (StrUtil.isEmpty(request.getRespondent())) {
            builder.setStatus(RpcStatusResult.error("答卷信息为空！"));
            responseObserver.onNext(builder.build());
            responseObserver.onCompleted();
            return;
        }

        // 参数转换
        GetRequestAwardParam getRequestAwardParam = requestToRequestAwardParam(request);
        // 参数校验
        Set<ConstraintViolation<Object>> violations = GRpcUtil.validateParam(getRequestAwardParam);
        if (!CollectionUtils.isEmpty(violations)) {
            ConstraintViolation<Object> violation = violations.iterator().next();
            builder.setStatus(RpcStatusResult.error(violation.getMessage()));
            responseObserver.onNext(builder.build());
            responseObserver.onCompleted();
            return;
        }

        ServiceResult<String> result = awardDispatcher.requestAward(getRequestAwardParam);

        if (result.isSuccess()) {
            builder.setData(result.getData());
            builder.setStatus(RpcStatusResult.success());
        } else {
            builder.setStatus(RpcStatusResult.error(result.getMsg()));
        }

        responseObserver.onNext(builder.build());
        responseObserver.onCompleted();
    }

    @Override
    public void getRequestRecord(GetRequestRecordRequest request, StreamObserver<GetRequestRecordResponse> responseObserver) {
        GetRequestRecordResponse.Builder builder = GetRequestRecordResponse.newBuilder();
        String requestId = request.getId();
        if (StrUtil.isEmpty(requestId)) {
            builder.setStatus(RpcStatusResult.error("请求id为空！"));
            responseObserver.onNext(builder.build());
            responseObserver.onCompleted();
            return;
        }
        ServiceResult<AwardRequestDO> serviceResult = awardDispatcher.getAwardRequestById(requestId);
        if (serviceResult.isSuccess()) {
            AwardRequestDO data = serviceResult.getData();
            if (data == null || data.getStatus() == null) {
                if (data != null && data.getStatus() == null) {
                    log.error("奖励请求记录状态为空:{}", JSON.toJSONString(data));
                }
                builder.setStatus(RpcStatusResult.error("请求记录不存在！"));
                responseObserver.onNext(builder.build());
                responseObserver.onCompleted();
                return;
            } else {
                RequestRecord.Builder requestBuilder = RequestRecord.newBuilder();
                requestBuilder.setId(data.getId());
                requestBuilder.setAwardId(data.getAwardId());
                requestBuilder.setDeliver(JSON.toJSONString(data.getDeliver()));
                requestBuilder.setSurvey(JSON.toJSONString(data.getSurvey()));
                requestBuilder.setDeviceTypeValue(data.getTty() == null ? DeviceTypeEnum.PC.getIndex() : data.getTty());
                requestBuilder.setIp(data.getIp());
                requestBuilder.setStatusValue(data.getStatus());
                builder.setRecord(requestBuilder.build());
                builder.setStatus(RpcStatusResult.success());
                responseObserver.onNext(builder.build());
                responseObserver.onCompleted();
                return;
            }
        } else {
            builder.setStatus(RpcStatusResult.error(serviceResult.getMsg()));
            responseObserver.onNext(builder.build());
            responseObserver.onCompleted();
            return;
        }

    }

    /**
     * 参数转换
     *
     * @param request 请求参数
     * @return GetRequestAwardParam
     */
    private GetRequestAwardParam requestToRequestAwardParam(GetRequestAwardRequest request) {
        GetRequestAwardParam getRequestAwardParam = new GetRequestAwardParam();
        getRequestAwardParam.setIp(request.getIp());
        JSONObject deliver = JSON.parseObject(request.getDeliver());
        getRequestAwardParam.setDeliverMap(deliver);
        getRequestAwardParam.setDeliver(JSON.parseObject(request.getDeliver(), AwardRequestDO.Deliver.class));

        AwardRequestDO.Survey survey = JSON.parseObject(request.getRespondent(), AwardRequestDO.Survey.class);

        getRequestAwardParam.setSurvey(survey);
        getRequestAwardParam.setDeviceType(request.getDeviceTypeValue());
        getRequestAwardParam.setVisitedCount(request.getVisitedCount());
        return getRequestAwardParam;
    }
}
